package com.corner.model.cornerservice.helper;

import com.alibaba.fastjson.JSONObject;
import com.corner.app.ConsTants;
import com.corner.model.cornerservice.domain.BaseBean;
import com.corner.model.cornerservice.domain.GeoPoint;
import com.corner.model.cornerservice.domain.Info;
import com.corner.model.cornerservice.domain.Location;
import com.corner.model.cornerservice.domain.User;
import com.corner.model.cornerservice.service.Service;
import com.corner.model.cornerservice.service.exception.BaseException;
import com.corner.model.cornerservice.utils.CQLUtil;
import com.corner.model.cornerservice.utils.ServiceQuery;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;

import rx.Observable;
import rx.Subscriber;
import rx.schedulers.Schedulers;

/**
 * Created by Administrator on 2015/7/23，09.28.
 * 描述：
 */
public class LocationHelper {
    /**
     * 通过地点获取Location信息
     * @param location
     * @param limit
     * @param skip
     */
    public static Observable<List<Location>> getLocations(final GeoPoint location, final int limit, final int skip) {
        return Observable.create(new Observable.OnSubscribe<List<Location>>() {
            @Override
            public void call(Subscriber<? super List<Location>> subscriber) {
                try {
                    String cql = "select l from Location l  where isValid=true" +
                            " and (select count(*) from Info where isValid=true and area.objectId = l.objectId and " +
                            "objectId not in (select l.info.objectId from Like l where type = 3 and l.user.objectId = 1))>0" +
                            " order by " + CQLUtil.formatNearCQL(location, "l.geoPoint");
                    Object result = Service.getInstance().cqlService.excuteCQL(URLEncoder.encode(cql, ConsTants.ENCODING), limit, skip);
                    List<Location> locations = JSONObject.parseArray(JSONObject.toJSONString(result), Location.class);
                    subscriber.onNext(locations);
                } catch (BaseException|UnsupportedEncodingException e) {
                    e.printStackTrace();
                    subscriber.onError(new Throwable());
                }
            }
        }).subscribeOn(Schedulers.io());
    }

    public static Observable<Location> getLocation(final Long locationId) {
        return Observable.create(new Observable.OnSubscribe<Location>() {
            @Override
            public void call(Subscriber<? super Location> subscriber) {
                try {
                    Location location = Service.getInstance().locationService.get(locationId);
                    subscriber.onNext(location);
                } catch (BaseException e) {
                    subscriber.onError(new Throwable());
                }
            }
        }).subscribeOn(Schedulers.io());
    }

    /**
     * @param location
     */
    public static Observable<User> getLocationUser(final Location location) {
        return Observable.create(new Observable.OnSubscribe<User>() {
            @Override
            public void call(Subscriber<? super User> subscriber) {
                try {
                    ServiceQuery query = new ServiceQuery();
                    query.setLimit(1);
                    query.equal(Info.AREA, location.getObjectId(), ServiceQuery.FOREIGN_KEY);
                    query.descenderBy(BaseBean.UPDATED_AT);
                    List<Info> infos = Service.getInstance().infoService.list(query.toString());
                    if (infos != null && infos.size() > 0) {
                        subscriber.onNext(infos.get(0).getUser());
                    } else {
                        subscriber.onNext(null);
                    }
                } catch (BaseException e) {
                    if (e.getCode().equals(BaseException.QueryNoResult)){
                        subscriber.onNext(null);
                    }else {
                        subscriber.onError(e);
                    }
                }
            }
        }).subscribeOn(Schedulers.io());
    }

    /**
     * @param location
     */
    public static Observable<Long> getContentsNum(final Location location) {
        return Observable.create(new Observable.OnSubscribe<Long>() {
            @Override
            public void call(Subscriber<? super Long> subscriber) {
                try {
                    ServiceQuery query = new ServiceQuery();
                    query.equal(Info.AREA, location.getObjectId(), ServiceQuery.FOREIGN_KEY);
                    Map<String, Long> count = Service.getInstance().infoService.
                            count(query.toString());
                    subscriber.onNext(count.get(Service.COUNT));
                } catch (BaseException e) {
                    if (e.getCode().equals(BaseException.QueryNoResult)){
                        subscriber.onNext(0L);
                    }else {
                        subscriber.onError(new Throwable());
                    }
                }
            }
        }).subscribeOn(Schedulers.io());
    }

    /**
     * @param locationName
     */
    public static Observable<Location> getLocationByName(final String locationName, final GeoPoint geoPoint) {
        return Observable.create(new Observable.OnSubscribe<Location>() {
            @Override
            public void call(Subscriber<? super Location> subscriber) {
                try {
                    ServiceQuery query = new ServiceQuery();
                    query.near(Location.GEO_POINT, geoPoint);
                    query.equal(Location.LOCATION_NAME, locationName, ServiceQuery.PROPERTY);
                    query.descenderBy(Location.UPDATED_AT);
                    query.setLimit(1);
                    List<Location> locations = Service.getInstance().locationService
                            .list(query.toString());
                    if (locations != null && locations.size() > 0) {
                        subscriber.onNext(locations.get(0));
                    } else {
                        subscriber.onNext(null);
                    }
                } catch (BaseException e) {
                    e.printStackTrace();
                    subscriber.onError(new Throwable());
                }
            }
        }).subscribeOn(Schedulers.io());
    }

    /**
     * 保存位置
     *
     * @param location
     * @return
     */
    public static Observable<Location> saveLocation(final Location location) {
        return Observable.create(new Observable.OnSubscribe<Location>() {
            @Override
            public void call(Subscriber<? super Location> subscriber) {
                try {
                    Map<String, Object> map = Service.getInstance().locationService.save(location);
                    JSONObject jsonObject = new JSONObject(map);
                    location.setObjectId(jsonObject.getLong(Service.OBJECT_ID));
                    subscriber.onNext(location);
                } catch (BaseException e) {
                    e.printStackTrace();
                    subscriber.onError(new Throwable());
                }
            }
        }).subscribeOn(Schedulers.io());
    }
}
